<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cain AI聊天</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3B82F6',
            secondary: '#64748B',
            success: '#10B981',
            warning: '#F59E0B',
            danger: '#EF4444',
            dark: '#1E293B',
            light: '#F8FAFC',
            chatbg: '#F1F5F9',
            chatmsg: '#E2E8F0',
            ollama: '#165DFF'
          },
          fontFamily: {
            inter: ['Inter', 'sans-serif'],
          },
        }
      }
    }
  </script>
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .scrollbar-hide {
        -ms-overflow-style: none;
        scrollbar-width: none;
      }
      .scrollbar-hide::-webkit-scrollbar {
        display: none;
      }
      .message-appear {
        animation: fadeIn 0.3s ease-in-out;
      }
      @keyframes fadeIn {
        from { opacity: 0; transform: translateY(10px); }
        to { opacity: 1; transform: translateY(0); }
      }
      .typing-animation {
        display: inline-flex;
        align-items: center;
      }
      .typing-animation span {
        height: 8px;
        width: 8px;
        margin: 0 2px;
        background-color: #3B82F6;
        border-radius: 50%;
        display: inline-block;
        animation: typing-bounce 1.4s infinite ease-in-out both;
      }
      .typing-animation span:nth-child(1) { animation-delay: -0.32s; }
      .typing-animation span:nth-child(2) { animation-delay: -0.16s; }
      @keyframes typing-bounce {
        0%, 80%, 100% { transform: scale(0); }
        40% { transform: scale(1); }
      }
    }
  </style>
</head>
<body class="font-inter bg-gray-100 min-h-screen flex flex-col">
<header class="bg-white shadow-sm py-4 px-6 sticky top-0 z-10">
  <div class="container mx-auto flex justify-between items-center">
    <h1 class="text-xl font-bold text-dark flex items-center">
      <i class="fa fa-robot text-ollama mr-2"></i>
      Cain AI聊天
    </h1>
    <div class="flex items-center">
      <button id="themeToggle" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
        <i class="fa fa-moon-o text-gray-600"></i>
      </button>
      <div id="connectionStatus" class="ml-4 flex items-center">
        <span id="statusIndicator" class="w-2 h-2 rounded-full bg-gray-400 mr-2"></span>
        <span id="statusText" class="text-sm text-gray-600">未连接</span>
      </div>
    </div>
  </div>
</header>

<main class="flex-grow container mx-auto p-4 md:p-6">
  <div class="max-w-4xl mx-auto bg-white rounded-xl shadow-lg overflow-hidden h-[calc(100vh-12rem)] flex flex-col">
    <!-- 聊天头部 -->
    <div class="p-4 border-b border-gray-200 flex justify-between items-center">
      <div class="flex items-center">
        <div class="relative">
          <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-10 h-10 rounded-full object-cover">
          <span class="absolute bottom-0 right-0 w-3 h-3 bg-success rounded-full border-2 border-white"></span>
        </div>
        <div class="ml-3">
          <h2 class="font-bold text-dark">Cain AI</h2>
          <p class="text-xs text-gray-500">基于本地模型的AI助手</p>
        </div>
      </div>
      <div class="flex space-x-2">
        <button id="clearChat" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
          <i class="fa fa-trash-o text-gray-600"></i>
        </button>
        <button id="settingsBtn" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
          <i class="fa fa-cog text-gray-600"></i>
        </button>
      </div>
    </div>

    <!-- 聊天内容区 -->
    <div class="flex-grow flex flex-col bg-chatbg">
      <div id="messageContainer" class="flex-grow p-4 overflow-y-auto scrollbar-hide">
        <div class="text-center my-4">
          <span class="bg-gray-200 text-gray-500 text-xs px-3 py-1 rounded-full" id="loginTime"></span>
        </div>

        <!-- 欢迎消息 -->
        <div class="flex mb-4 message-appear">
          <div class="mr-2">
            <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-8 h-8 rounded-full object-cover">
          </div>
          <div>
            <div class="text-xs text-gray-500 mb-1">Cain AI</div>
            <div class="bg-ollama text-white rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
              <p>你好！我是基于Cain的AI助手。请问有什么可以帮助你的吗？</p>
            </div>
            <div class="text-xs text-gray-500 mt-1" id="time"></div>
          </div>
        </div>

        <!-- 消息将通过JS动态生成 -->
      </div>

      <!-- 输入区域 -->
      <div class="p-4 border-t border-gray-200">
        <div class="flex space-x-2 mb-2">
          <button id="voiceInput" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
            <i class="fa fa-microphone text-gray-600"></i>
          </button>
          <button id="fileUpload" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
            <i class="fa fa-paperclip text-gray-600"></i>
          </button>
        </div>
        <div class="flex">
          <input id="messageInput" type="text" placeholder="输入问题..." class="flex-grow px-4 py-2 rounded-l-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
          <button id="sendBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-r-lg transition-colors">
            发送
          </button>
        </div>
      </div>
    </div>
  </div>
</main>

<footer class="bg-dark text-white py-4 px-6">
  <div class="container mx-auto text-center text-sm text-gray-400">
    <p>Cain AI聊天示例 &copy; 2025</p>
  </div>
</footer>

<!-- 设置模态框 -->
<div id="settingsModal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 hidden">
  <div class="bg-white rounded-xl shadow-xl w-full max-w-md p-6 transform scale-95 opacity-0 transition-all duration-300" id="modalContent">
    <div class="flex justify-between items-center mb-4">
      <h3 class="text-xl font-bold text-dark">Ai助手设置</h3>
      <button id="closeSettings" class="text-gray-400 hover:text-gray-600">
        <i class="fa fa-times"></i>
      </button>
    </div>
    <div class="space-y-4">
      <div>
        <label for="ollamaUrl" class="block text-sm font-medium text-gray-700 mb-1">Cain API地址</label>
        <input type="text" id="ollamaUrl" value="http://localhost:11434/api/chat" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
      </div>
      <div>
        <label for="model" class="block text-sm font-medium text-gray-700 mb-1">模型名称</label>
        <input type="text" id="model" value="gemma3" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
      </div>
      <div>
        <label for="temperature" class="block text-sm font-medium text-gray-700 mb-1">温度 (创造性)</label>
        <div class="flex items-center">
          <input type="range" id="temperature" min="0" max="1" step="0.1" value="0.7" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
          <span id="tempValue" class="ml-2 text-sm font-medium text-gray-700">0.7</span>
        </div>
      </div>
      <div class="pt-2">
        <button id="saveSettings" class="w-full bg-primary hover:bg-primary/90 text-white py-2 rounded-lg transition-colors">
          保存设置
        </button>
      </div>
    </div>
  </div>
</div>

<script>
  // 配置参数
  let config = {
    ollamaUrl: 'http://localhost:11434/api/chat',
    model: 'gemma3',
    temperature: 0.7
  };

  // 聊天状态
  let isWaitingForResponse = false;

  // DOM元素
  const messageContainer = $('#messageContainer');
  const messageInput = $('#messageInput');
  const sendBtn = $('#sendBtn');
  const statusIndicator = $('#statusIndicator');
  const statusText = $('#statusText');
  const settingsModal = $('#settingsModal');
  const modalContent = $('#modalContent');
  const closeSettings = $('#closeSettings');
  const saveSettings = $('#saveSettings');
  const ollamaUrl = $('#ollamaUrl');
  const model = $('#model');
  const temperature = $('#temperature');
  const tempValue = $('#tempValue');
  const clearChat = $('#clearChat');

  // 显示设置模态框
  function showSettingsModal() {
    // 填充当前设置
    ollamaUrl.val(config.ollamaUrl);
    model.val(config.model);
    temperature.val(config.temperature);
    tempValue.text(config.temperature);

    settingsModal.removeClass('hidden');
    setTimeout(() => {
      modalContent.removeClass('scale-95 opacity-0').addClass('scale-100 opacity-100');
    }, 10);
  }

  // 隐藏设置模态框
  function hideSettingsModal() {
    modalContent.removeClass('scale-100 opacity-100').addClass('scale-95 opacity-0');
    setTimeout(() => {
      settingsModal.addClass('hidden');
    }, 300);
  }

  // 更新连接状态
  function updateConnectionStatus(isConnected) {
    if (isConnected) {
      statusIndicator.removeClass('bg-gray-400').addClass('bg-success');
      statusText.text('已连接');
    } else {
      statusIndicator.removeClass('bg-success').addClass('bg-gray-400');
      statusText.text('未连接');
    }
  }

  // 发送消息到Ollama
  function sendMessageToOllama(prompt) {
    if (isWaitingForResponse) {
      return;
    }

    isWaitingForResponse = true;
    updateConnectionStatus(true);

    // 添加用户消息
    const timestamp = new Date().toISOString();
    const time = new Date(timestamp).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});

    const userMessage = $(`
                <div class="flex justify-end mb-4 message-appear">
                    <div>
                        <div class="text-right text-xs text-gray-500 mb-1">你</div>
                        <div class="bg-primary text-white rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            <p>${prompt}</p>
                        </div>
                        <div class="text-right text-xs text-gray-500 mt-1">${time}</div>
                    </div>
                    <div class="ml-2">
                        <img src="https://picsum.photos/id/105/40/40" alt="你" class="w-8 h-8 rounded-full object-cover">
                    </div>
                </div>
            `);

    messageContainer.append(userMessage);

    // 添加AI正在输入的状态
    const typingIndicator = $(`
                <div id="typingIndicator" class="flex mb-4 message-appear">
                    <div class="mr-2">
                        <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-8 h-8 rounded-full object-cover">
                    </div>
                    <div>
                        <div class="text-xs text-gray-500 mb-1">Cain AI</div>
                        <div class="bg-ollama/10 text-gray-800 rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            <div class="typing-animation">
                                <span></span>
                                <span></span>
                                <span></span>
                            </div>
                        </div>
                    </div>
                </div>
            `);

    messageContainer.append(typingIndicator);
    messageContainer.scrollTop(messageContainer[0].scrollHeight);

    // 准备请求数据
    const requestData = {
      model: config.model,
      messages: [
        { role: "user", content: prompt }
      ],
      stream: true,
      options: {
        temperature: config.temperature
      }
    };

    // 创建AI响应元素
    const responseTime = new Date().toISOString();
    const responseTimeDisplay = new Date(responseTime).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});

    const aiResponseContainer = $(`
                <div id="aiResponseContainer" class="flex mb-4 hidden message-appear">
                    <div class="mr-2">
                        <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-8 h-8 rounded-full object-cover">
                    </div>
                    <div>
                        <div class="text-xs text-gray-500 mb-1">Cain AI</div>
                        <div class="bg-ollama text-white rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            <p id="aiResponse"></p>
                        </div>
                        <div class="text-xs text-gray-500 mt-1">${responseTimeDisplay}</div>
                    </div>
                </div>
            `);

    // 使用Fetch API发送请求并处理流式响应
    fetch(config.ollamaUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestData)
    })
            .then(response => {
              if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
              }

              // 移除"正在输入"指示器
              typingIndicator.remove();

              // 显示响应容器
              messageContainer.append(aiResponseContainer);
              aiResponseContainer.removeClass('hidden');

              const reader = response.body.getReader();
              const decoder = new TextDecoder();
              let aiResponse = '';

              // 处理流式响应
              function readStream() {
                reader.read().then(({ done, value }) => {
                  if (done) {
                    isWaitingForResponse = false;
                    updateConnectionStatus(false);
                    return;
                  }

                  // 解码数据
                  const chunk = decoder.decode(value, { stream: true });

                  // 解析JSON行
                  const lines = chunk.split('\n').filter(line => line.trim() !== '');

                  lines.forEach(line => {
                    try {
                      const data = JSON.parse(line);
                      if (data.message && data.message.content) {
                        aiResponse += data.message.content;
                        $('#aiResponse').text(aiResponse);
                        messageContainer.scrollTop(messageContainer[0].scrollHeight);
                      }
                    } catch (error) {
                      console.error('Error parsing JSON:', error);
                    }
                  });

                  // 继续读取流
                  readStream();
                }).catch(error => {
                  console.error('Error reading stream:', error);
                  isWaitingForResponse = false;
                  updateConnectionStatus(false);
                });
              }

              readStream();
            })
            .catch(error => {
              // 移除"正在输入"指示器
              typingIndicator.remove();

              // 显示错误消息
              const errorMessage = $(`
                    <div class="flex mb-4 message-appear">
                        <div class="mr-2">
                            <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-8 h-8 rounded-full object-cover">
                        </div>
                        <div>
                            <div class="text-xs text-gray-500 mb-1">Cain AI</div>
                            <div class="bg-danger/10 text-danger rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                                <p>发生错误: ${error.message}</p>
                                <p>请检查Cain服务是否正在运行</p>
                            </div>
                        </div>
                    </div>
                `);

              messageContainer.append(errorMessage);
              messageContainer.scrollTop(messageContainer[0].scrollHeight);

              isWaitingForResponse = false;
              updateConnectionStatus(false);
            });
  }

  // 清空聊天
  function clearChatMessages() {
    messageContainer.empty();

    // 添加欢迎消息
    const welcomeMessage = $(`
                <div class="text-center my-4">
                    <span class="bg-gray-200 text-gray-500 text-xs px-3 py-1 rounded-full">今天 ${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>
                </div>
                <div class="flex mb-4 message-appear">
                    <div class="mr-2">
                        <img src="https://picsum.photos/id/237/40/40" alt="Cain AI" class="w-8 h-8 rounded-full object-cover">
                    </div>
                    <div>
                        <div class="text-xs text-gray-500 mb-1">Cain AI</div>
                        <div class="bg-ollama text-white rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            <p>你好！我是基于Cain的AI助手。请问有什么可以帮助你的吗？</p>
                        </div>
                        <div class="text-xs text-gray-500 mt-1">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</div>
                    </div>
                </div>
            `);

    messageContainer.append(welcomeMessage);
  }

  // 事件绑定
  $(document).ready(function() {
    var date = new Date();
    var hours = date.getHours();
    var minutes = date.getMinutes();
    $("#loginTime").text("今天 "+hours+":"+minutes);
    $("#time").text(hours+":"+minutes);
    // 初始化设置
    temperature.on('input', function() {
      tempValue.text(this.value);
    });

    // 设置按钮点击事件
    $('#settingsBtn').on('click', showSettingsModal);

    // 关闭设置模态框按钮点击事件
    closeSettings.on('click', hideSettingsModal);

    // 保存设置按钮点击事件
    saveSettings.on('click', function() {
      config.ollamaUrl = ollamaUrl.val().trim();
      config.model = model.val().trim();
      config.temperature = parseFloat(temperature.val());

      hideSettingsModal();
      showSettingsModal(); // 重新打开以显示新设置
    });

    // 发送消息按钮点击事件
    sendBtn.on('click', function() {
      const message = messageInput.val().trim();
      if (message && !isWaitingForResponse) {
        sendMessageToOllama(message);
        messageInput.val('');
        messageInput.focus();
      }
    });

    // 输入框回车发送消息
    messageInput.on('keypress', function(e) {
      if (e.which === 13) { // Enter键
        sendBtn.click();
      }
    });

    // 清空聊天按钮点击事件
    clearChat.on('click', function() {
      if (!isWaitingForResponse) {
        clearChatMessages();
      }
    });

    // 主题切换按钮点击事件
    $('#themeToggle').on('click', function() {
      const icon = $(this).find('i');
      if (icon.hasClass('fa-moon-o')) {
        icon.removeClass('fa-moon-o').addClass('fa-sun-o');
        // 这里可以添加暗色主题切换逻辑
      } else {
        icon.removeClass('fa-sun-o').addClass('fa-moon-o');
        // 这里可以添加亮色主题切换逻辑
      }
    });

    // 语音输入按钮点击事件
    $('#voiceInput').on('click', function() {
      if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) {
        const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
        recognition.lang = 'zh-CN';

        recognition.onresult = function(event) {
          const speechResult = event.results[0][0].transcript;
          messageInput.val(speechResult);
        };

        recognition.onerror = function(event) {
          console.error('语音识别错误:', event.error);
        };

        recognition.onend = function() {
          // 语音识别结束
        };

        recognition.start();
      } else {
        alert('抱歉，您的浏览器不支持语音输入功能');
      }
    });

    // 文件上传按钮点击事件
    $('#fileUpload').on('click', function() {
      alert('文件上传功能正在开发中');
    });
  });
</script>
</body>
</html>
